package com.file.parser;

import com.file.bo.IIT;
import com.file.bo.IITTran;
import com.file.bo.ResponseData;
import com.file.constant.EfpConstants;
import com.file.constant.ErrorCode;
import com.file.util.JsonUtils;
import com.google.common.base.Splitter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Slf4j
public class IITPdfParser extends BaseDecryptPdfParser {

	public ResponseData<String> parseIITPdfToJson(String filePath, String pdfPassword) {
		log.info("parseIITPdfToJson started, filePath:{}, pdfPassword:{}", filePath, pdfPassword);
		String json = null;

		try {
			IIT iit = parseIITPdf(filePath, pdfPassword);
			json = JsonUtils.convertObjectToJson(iit);
		} catch (Exception e) {
			log.error("[OnError]parseIITPdfToJson failed, daId:{}, pdfPassword:{}", filePath, pdfPassword, e);
			return new ResponseData<String>(json, ErrorCode.FILE_PARSE_EXCEPTION.getCode(),
					ErrorCode.FILE_PARSE_EXCEPTION.getMsg());
		}

		log.info("parseIITPdfToJson completed, filePath:{}, pdfPassword:{}", filePath, pdfPassword);
		return new ResponseData<String>(json, ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg());
	}
	


	public IIT parseIITPdf(String filePath, String pdfPassword) {
		IIT iit = parseIITHeader(filePath, pdfPassword);

		List<IITTran> iitTrans = new ArrayList<>();
		iitTrans = parseIITTrans(filePath, pdfPassword);


		iit.setIitTrans(iitTrans);
		return iit;
	}

	public IIT parseIITHeader(String filePath, String pdfPassword) {
		IIT iit = new IIT();
		String pdfHeaderText = parsePdfHeaderText(filePath, pdfPassword);
		String recordPeriod = pdfHeaderText
				.substring(pdfHeaderText.indexOf("记 录 期 间 :") + 9, pdfHeaderText.indexOf("纳 税 ⼈ 名 称 : ")).trim();
		String taxpayerName = pdfHeaderText
				.substring(pdfHeaderText.indexOf("纳 税 ⼈ 名 称 :") + 11, pdfHeaderText.indexOf("纳税⼈识别号:")).trim();
		String taxpayerIdNo = pdfHeaderText
				.substring(pdfHeaderText.indexOf("纳税⼈识别号:") + 7, pdfHeaderText.indexOf("⾝份证件类型:")).trim();
		String IdCardType = pdfHeaderText
				.substring(pdfHeaderText.indexOf("⾝份证件类型:") + 7, pdfHeaderText.indexOf("⾝份证件号码:")).trim();
		String idNo = pdfHeaderText.substring(pdfHeaderText.indexOf("⾝份证件号码:") + 7, pdfHeaderText.indexOf("⾦额单位:"))
				.trim();
		String amountUnit = pdfHeaderText.substring(pdfHeaderText.indexOf("⾦额单位:") + 5, pdfHeaderText.indexOf("申报⽇期"))
				.trim();
		String issueDate = pdfHeaderText
				.substring(pdfHeaderText.indexOf("开具时间：") + 5, pdfHeaderText.indexOf("本凭证不作为纳税⼈记账")).trim();

		iit.setRecordPeriod(recordPeriod);
		iit.setTaxpayerName(taxpayerName);
		iit.setTaxpayerIdNo(taxpayerIdNo);
		iit.setIdCardType(IdCardType);
		iit.setIdNo(idNo);
		iit.setAmountUnit(amountUnit);
		iit.setIssueDate(issueDate);

		return iit;
	}



	public List<IITTran> parseIITTrans(String filePath, String pdfPassword) {
		List<IITTran> iitTrans = new ArrayList<>();

		String pdfText = getPdfTextByStripper(filePath, pdfPassword);
		pdfText = pdfText.replace(System.getProperty("line.separator", "\n"), " ");		
		
		// 此处认为”申报日期不为空“，且格式为YYYY.MM.DD;同时”实缴（退）金额“不为空，且格式为AA.BB，A为1-9位数；同时每列之间有空格分隔。
		Pattern pattern1 = Pattern.compile("\\d{4}.\\d{2}.\\d{2}\\s\\d{1,9}.\\d{2}");
		Matcher matcher1 = pattern1.matcher(pdfText);

		// 每行交易记录的第一个字所在的index
		int tranIndex = 0;
		Map<Integer, Integer> tranTextStartIndexMap = new HashMap<>();

		while (matcher1.find()) {
//			log.info(
//					"Match \"" + matcher1.group() + "\" at positions " + matcher1.start() + "-" +
//							(matcher1.end() - 1));
			tranTextStartIndexMap.put(tranIndex, matcher1.start());
			tranIndex++;
		}

		// 找出每行交易记录的文本
		List<String> tranTextList = new ArrayList<>();
		for (int i = 1; i < tranTextStartIndexMap.size(); i++) {
			String tranText = pdfText.substring(tranTextStartIndexMap.get(i - 1), tranTextStartIndexMap.get(i));
//			log.info("tranText = " + tranText);
			if (tranText.contains("⾦额合计")) {
				tranText = tranText.substring(0, tranText.indexOf("⾦额合计")).trim();
			}
//			log.info(tranText);
			tranTextList.add(tranText);
		}

		String lastTranText = pdfText.substring(tranTextStartIndexMap.get(tranTextStartIndexMap.size() - 1));
		if (lastTranText.contains("⾦额合计")) {
			lastTranText = lastTranText.substring(0, lastTranText.indexOf("⾦额合计")).trim();
		}
//		log.info(lastTranText);
		tranTextList.add(lastTranText);

		Pattern pattern2 = Pattern.compile("\\d{4}.\\d{2}");
		for (String tranText : tranTextList) {
			List<String> tranTextFields = new ArrayList<>(Splitter.on(" ").omitEmptyStrings().splitToList(tranText));
			log.info(lastTranText);
			//这里加多一个处理，处理所得项目有换行的情况
			Matcher matcher2 = pattern2.matcher(tranTextFields.get(4));
			//如果第5个字段所属税款期如果不是2021.09这样的内容，那就是所的项目字段出现了换行
			if (!matcher2.find()) {
				tranTextFields.set(3, tranTextFields.get(3) + tranTextFields.get(4));
				for (int i = 5; i < tranTextFields.size(); i++) {
					tranTextFields.set(i-1, tranTextFields.get(i));
				}
				tranTextFields.remove(tranTextFields.size() -1);
			}
			
			//解决所得项目有3行的case
			matcher2 = pattern2.matcher(tranTextFields.get(4));
			if (!matcher2.find()) {
				tranTextFields.set(3, tranTextFields.get(3) + tranTextFields.get(4));
				for (int i = 5; i < tranTextFields.size(); i++) {
					tranTextFields.set(i-1, tranTextFields.get(i));
				}
				tranTextFields.remove(tranTextFields.size() -1);
			}
			
			
//			log.info("tranTextFields = " + tranTextFields.toString());
			IITTran iitTran = new IITTran();
			//pdf里有七个字段，且前六个字段不会为空
			if (tranTextFields.size() == 6) {
				////税款所属期后split出一个字段，备注为空，且入库税务机关没有换行
				iitTran.setDeclarationDate(tranTextFields.get(0));
				iitTran.setPaidInOutAmount(tranTextFields.get(1));
				iitTran.setStockInOutDate(tranTextFields.get(2));
				iitTran.setIncomeItem(tranTextFields.get(3));
				iitTran.setTaxPeriod(tranTextFields.get(4));
				iitTran.setStockInTaxAuthority(tranTextFields.get(5));
				iitTran.setComment("");
				iitTrans.add(iitTran);
			} else if (tranTextFields.size() == 7) {
				//税款所属期后split出两个字段，这里有两种情况，就是1.入库税务机关没有换行，且有备注，2入库税务机关有换行，没有备注 这里通过判断tranTextField6有没有税务局来判断
				if (tranTextFields.get(6).endsWith("局")) {
					iitTran.setDeclarationDate(tranTextFields.get(0));
					iitTran.setPaidInOutAmount(tranTextFields.get(1));
					iitTran.setStockInOutDate(tranTextFields.get(2));
					iitTran.setIncomeItem(tranTextFields.get(3));
					iitTran.setTaxPeriod(tranTextFields.get(4));
					iitTran.setStockInTaxAuthority(tranTextFields.get(5) + tranTextFields.get(6));
					iitTran.setComment("");
				} else {
					iitTran.setDeclarationDate(tranTextFields.get(0));
					iitTran.setPaidInOutAmount(tranTextFields.get(1));
					iitTran.setStockInOutDate(tranTextFields.get(2));
					iitTran.setIncomeItem(tranTextFields.get(3));
					iitTran.setTaxPeriod(tranTextFields.get(4));
					iitTran.setStockInTaxAuthority(tranTextFields.get(5));
					iitTran.setComment(tranTextFields.get(6));
				}
				iitTrans.add(iitTran);
			} else if (tranTextFields.size() == 8) {
				//税款所属期后split出三个字段
				//入库税务机关有换行且备注不为空				
				if (tranTextFields.get(6).endsWith("局")) {
					iitTran.setDeclarationDate(tranTextFields.get(0));
					iitTran.setPaidInOutAmount(tranTextFields.get(1));
					iitTran.setStockInOutDate(tranTextFields.get(2));
					iitTran.setIncomeItem(tranTextFields.get(3));
					iitTran.setTaxPeriod(tranTextFields.get(4));
					iitTran.setStockInTaxAuthority(tranTextFields.get(5) + tranTextFields.get(6));
					iitTran.setComment(tranTextFields.get(7));
				} else if (tranTextFields.get(7).endsWith("局")){
					//入库税务机关有三行的case
					iitTran.setDeclarationDate(tranTextFields.get(0));
					iitTran.setPaidInOutAmount(tranTextFields.get(1));
					iitTran.setStockInOutDate(tranTextFields.get(2));
					iitTran.setIncomeItem(tranTextFields.get(3));
					iitTran.setTaxPeriod(tranTextFields.get(4));
					iitTran.setStockInTaxAuthority(tranTextFields.get(5) + tranTextFields.get(6) + tranTextFields.get(7));
					iitTran.setComment("");
				} else {
					//入库税务机关无换行且备注有两行
					iitTran.setDeclarationDate(tranTextFields.get(0));
					iitTran.setPaidInOutAmount(tranTextFields.get(1));
					iitTran.setStockInOutDate(tranTextFields.get(2));
					iitTran.setIncomeItem(tranTextFields.get(3));
					iitTran.setTaxPeriod(tranTextFields.get(4));
					iitTran.setStockInTaxAuthority(tranTextFields.get(5));
					iitTran.setComment(tranTextFields.get(6) + tranTextFields.get(7));
				}
				iitTrans.add(iitTran);
			} else if (tranTextFields.size() == 9) {				
				//税款所属期后split出四个字段
				if (tranTextFields.get(6).endsWith("局")) {
					//备注不为空且换行，且入库税务机关有换行
					iitTran.setDeclarationDate(tranTextFields.get(0));
					iitTran.setPaidInOutAmount(tranTextFields.get(1));
					iitTran.setStockInOutDate(tranTextFields.get(2));
					iitTran.setIncomeItem(tranTextFields.get(3));
					iitTran.setTaxPeriod(tranTextFields.get(4));
					iitTran.setStockInTaxAuthority(tranTextFields.get(5) + tranTextFields.get(6));
					iitTran.setComment(tranTextFields.get(7) + tranTextFields.get(8));
				} else if (tranTextFields.get(7).endsWith("局")) {
					//入库税务机关有三行的case
					iitTran.setDeclarationDate(tranTextFields.get(0));
					iitTran.setPaidInOutAmount(tranTextFields.get(1));
					iitTran.setStockInOutDate(tranTextFields.get(2));
					iitTran.setIncomeItem(tranTextFields.get(3));
					iitTran.setTaxPeriod(tranTextFields.get(4));
					iitTran.setStockInTaxAuthority(tranTextFields.get(5) + tranTextFields.get(6) + tranTextFields.get(7));
				} else {
					//入库税务机关为一行，且备注有三行
					iitTran.setDeclarationDate(tranTextFields.get(0));
					iitTran.setPaidInOutAmount(tranTextFields.get(1));
					iitTran.setStockInOutDate(tranTextFields.get(2));
					iitTran.setIncomeItem(tranTextFields.get(3));
					iitTran.setTaxPeriod(tranTextFields.get(4));
					iitTran.setStockInTaxAuthority(tranTextFields.get(5));
					iitTran.setComment(tranTextFields.get(6) + tranTextFields.get(7) + tranTextFields.get(8));
				}
				iitTrans.add(iitTran);
			} else {
				log.error("[OnError] This record is new case");
				throw new RuntimeException("this record contains new case");
			}
		}

		return iitTrans;
	}

	public static void main(String[] args) throws IOException {
//		String pdfFilePath = "E:\\data\\file\\iit\\381859402262513295_d0ed1c34fda5a640698578392ced6a38_tax_nsjl-055614.pdf";
//		String jsonFilePath = "E:\\data\\file\\iit\\381859402262513295_d0ed1c34fda5a640698578392ced6a38_tax_nsjl-055614.json";
//		String passWord = "055614";
//		String pdfFilePath = "E:\\data\\file\\iit\\381295244299215025_2f912da2c5dcbee03430d93b956f5961_tax_nsjl-272811.pdf";
//		String jsonFilePath = "E:\\data\\file\\iit\\381295244299215025_2f912da2c5dcbee03430d93b956f5961_tax_nsjl-272811.json";
//		String passWord = "272811";

		String pdfFilePath = "E:\\data\\file\\iit\\382006000938386319_01ffcc1ba1f9ac1aca08333f7f0aebb9_tax_nsjl-083661.pdf";
		String jsonFilePath = "E:\\data\\file\\iit\\382006000938386319_01ffcc1ba1f9ac1aca08333f7f0aebb9_tax_nsjl-083661.json";
		String passWord = "083661";

//		String pdfFilePath = "E:\\data\\file\\iit\\382581175476031254_7bce4e73aa481a85a2e6865ba9b72661_tax_nsjl-224757.pdf";
//		String jsonFilePath = "E:\\data\\file\\iit\\382581175476031254_7bce4e73aa481a85a2e6865ba9b72661_tax_nsjl-224757.json";
//		String passWord = "224757";
		
//		String pdfFilePath = "E:\\data\\file\\iit\\382127552405177999_a6783eef078e41bcc618a06cf70554aa_tax_nsjl-233231.pdf";
//		String jsonFilePath = "E:\\data\\file\\iit\\382127552405177999_a6783eef078e41bcc618a06cf70554aa_tax_nsjl-233231.json";
//		String passWord = "233231";
		
//		String pdfFilePath = "E:\\data\\file\\iit\\382885884011218575_7e6cce107c8a4837011eec1f7628c438_tax_nsjl-145166.pdf";
//		String jsonFilePath = "E:\\data\\file\\iit\\382885884011218575_7e6cce107c8a4837011eec1f7628c438_tax_nsjl-145166.json";
//		String passWord = "145166";
		
//		String pdfFilePath = "E:\\data\\file\\iit\\383307762106368911_ec2099b438809ee6962905e890c92518_tax_nsjl-161326.pdf";
//		String jsonFilePath = "E:\\data\\file\\iit\\383307762106368911_ec2099b438809ee6962905e890c92518_tax_nsjl-161326.json";
//		String passWord = "161326";
		


		File jsonFile = new File(jsonFilePath);
		IITPdfParser iitParser = new IITPdfParser();
		ResponseData<String> responseData = iitParser.parseIITPdfToJson(pdfFilePath, passWord);
		log.info(responseData.getData());
		FileUtils.write(jsonFile, responseData.getData(), EfpConstants.UTF_8);

		jsonFile.createNewFile();
	}

}
